package com.example.yibu.modelConfig.ascPool;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;

/***
  * @Message 异步执行器工厂
 *
 */
@Slf4j
@Component
public class AsyncFactory {

    @Autowired
    @Qualifier("scheduledExecutor")
    private ScheduledExecutorService scheduledExecutorService;


    /****
     *  pollIntervalMillis;  轮询间隔时间（毫秒）
     *  maxAttempts;  最大尝试次数
     *  Runnable task 用户提供的业务逻辑
     */


    /**
     * 执行轮询任务，不阻塞主线程，没有返回值
     */
    public void execute(final Runnable task,int pollIntervalMillis,int maxAttempts) {
        final AtomicBoolean done = new AtomicBoolean(false);
        final AtomicInteger attempts = new AtomicInteger(0);
        Runnable pollingTask = () -> {
            try {
                if (attempts.incrementAndGet() > maxAttempts || done.get()) {
                    log.error("轮询任务结束,已超过最大尝试次数");
                    return;
                }
                task.run(); // 执行业务逻辑
            } catch (Exception e) {
                log.error("轮询任务发生异常: ", e);
            }
        };
        scheduledExecutorService.scheduleAtFixedRate(pollingTask, 0, pollIntervalMillis, TimeUnit.MILLISECONDS);
    }


    /**
     * 执行轮询任务，并返回一个 CompletableFuture 用于等待任务完成并获取结果。
     *
     * @param task               用户提供的业务逻辑，应该返回一个结果
     * @param isComplete         用户提供的逻辑，用来检查结果是否表示任务已完成
     * @param pollIntervalMillis 轮询间隔时间（毫秒）
     * @param maxAttempts        最大尝试次数
     * @return CompletableFuture<T> 用于等待任务完成并获取结果
     */
    public <T> CompletableFuture<T> executeForResult(Callable<T> task, Predicate<T> isComplete, int pollIntervalMillis, int maxAttempts) {
        CompletableFuture<T> future = new CompletableFuture<>();
        PollingTask<T> pollingTask = new PollingTask<>(task, isComplete, maxAttempts, future);

        // 调度任务，并将 ScheduledFuture 传递给 PollingTask
        ScheduledFuture<?> scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(pollingTask, 0, pollIntervalMillis, TimeUnit.MILLISECONDS);
        pollingTask.setScheduledFuture(scheduledFuture); // 设置 ScheduledFuture

        log.info("等待结果的轮询任务已安排，间隔时间：{} 毫秒，最大尝试次数：{}", pollIntervalMillis, maxAttempts);
        return future;
    }

    private static class PollingTask<T> implements Runnable {

        private final Callable<T> task;
        private final Predicate<T> isComplete;
        private final int maxAttempts;
        private final AtomicBoolean done = new AtomicBoolean(false);
        private final AtomicInteger attempts = new AtomicInteger(0);
        private final CompletableFuture<T> future;

        private volatile ScheduledFuture<?> scheduledFuture; // 保存调度信息以便取消

        public PollingTask(Callable<T> task, Predicate<T> isComplete, int maxAttempts, CompletableFuture<T> future) {
            this.task = task;
            this.isComplete = isComplete;
            this.maxAttempts = maxAttempts;
            this.future = future;
        }

        public void setScheduledFuture(ScheduledFuture<?> scheduledFuture) {
            this.scheduledFuture = scheduledFuture;
        }

        @Override
        public void run() {
            try {
                int currentAttempt = attempts.incrementAndGet();

                if (currentAttempt > maxAttempts) {
                    log.warn("轮询任务达到最大尝试次数 {}，结束", maxAttempts);
                    future.completeExceptionally(new RuntimeException("轮询任务达到最大尝试次数"));
                    done.set(true);
                    cancelScheduledFuture();
                    return;
                }

                if (done.get()) {
                    log.info("轮询任务已标记为完成，结束");
                    return;
                }

                T result = task.call(); // 执行用户提供的业务逻辑，并获取结果

                if (result != null && isComplete.test(result)) {
                    log.info("轮询任务成功完成，结果: {}", result);
                    done.set(true);
                    future.complete(result); // 任务完成后完成 CompletableFuture 并返回结果
                    cancelScheduledFuture();
                } else {
                    log.debug("轮询任务尚未完成，当前尝试次数: {}", currentAttempt);
                }
            } catch (InterruptedException e) {
                log.warn("轮询任务被中断", e);
                Thread.currentThread().interrupt(); // 恢复中断状态
                done.set(true);
                future.completeExceptionally(e);
                cancelScheduledFuture();
            } catch (Exception e) {
                log.error("轮询任务发生异常: ", e);
                if (!done.get()) {
                    future.completeExceptionally(e);
                    done.set(true);
                    cancelScheduledFuture();
                }
            }
        }

        private void cancelScheduledFuture() {
            if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
                scheduledFuture.cancel(false); // 取消未来的调度，不中断正在执行的任务
            }
        }
    }
}
